<?php


namespace App\Http\Controllers\WebApi;


use App\Http\Controllers\WebApi\Business\AuthBusiness;
use App\Http\Controllers\WebApi\Business\OperationLogsBusiness;
use App\Models\ImAccount;
use App\Models\ImAuthItems;
use App\Models\ImOperationLogs;
use App\Models\ImRoleAuth;
use App\Models\ImRoleGroups;
use App\Models\ImAccountRoles;
use App\Models\ImSessionInfo;
use App\Validators\AuthValidator;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;

class AuthController
{
    private $authBusiness = null;//权限业务处理

    public function __construct(AuthBusiness $authBusiness)
    {
        $this->authBusiness = $authBusiness;
    }

    /**
     * 添加权限组
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function groupAdd(Request $request)
    {
        $param = $request->all();
        $valid = AuthValidator::handle($param, 'groupAdd');
        if (true !== $valid) {
            return errBack($valid->first());
        }
        $count = ImRoleGroups::where('name', $param['name'])->count();
        if ($count) {
            return errBack('名称重复');
        }
        $roleGroup = new ImRoleGroups();
        $roleGroup->name = $param['name'];
        $roleGroup->save();
        return okBack();
    }

    /**
     * 权限组列表
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function groupList(Request $request)
    {
        $data = ImRoleGroups::select(['id', 'name'])->get();
        return okBack($data);
    }

    /**
     * 编辑权限组
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function groupEdit(Request $request)
    {
        $param = $request->all();
        $valid = AuthValidator::handle($param, 'groupEdit');
        if (true !== $valid) {
            return errBack($valid->first());
        }
        $roleGroup = ImRoleGroups::find($param['id']);
        if (!$roleGroup) {
            return errBack('分组不存在');
        }
        $count = ImRoleGroups::where('name', $param['name'])
            ->where('id', '<>', $param['id'])->count();
        if ($count) {
            return errBack('名称重复');
        }
        $roleGroup->name = $param['name'];
        $roleGroup->save();
        return okBack();
    }

    /**
     * 删除权限组
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function groupDel(Request $request)
    {
        $param = $request->all();
        $valid = AuthValidator::handle($param, 'groupDel');
        if (true !== $valid) {
            return errBack($valid->first());
        }
        $group = ImRoleGroups::select('id')->find($param['id']);
        if (!$group) {
            return errBack('分组不存在');
        }
        $count = ImAccountRoles::where('group_id', $param['id'])->count();
        if ($count) {
            return errBack('请先删除所关联的角色');
        }
        $group->delete();
        return okBack();
    }

    /**
     * 添加角色
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function roleAdd(Request $request)
    {
        $param = $request->all();
        $valid = AuthValidator::handle($param, 'roleAdd');
        if (true !== $valid) {
            return errBack($valid->first());
        }
        $count = ImAccountRoles::where('name', $param['name'])->count();
        if ($count) {
            return errBack('名称重复');
        }
        $group = ImRoleGroups::where('id', $param['group_id'])->count();
        if (!$group) {
            return errBack('分组不存在');
        }
        $chatRole = new ImAccountRoles();
        $coding = getCode();
        $chatRole->name = $param['name'];
        $chatRole->coding = $coding;
        $chatRole->group_id = $param['group_id'];
        $chatRole->save();
        return okBack();
    }

    /**
     * 角色列表
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function roleList(Request $request)
    {
        $param = $request->all();
        $valid = AuthValidator::handle($param, 'roleList');
        if (true !== $valid) {
            return errBack($valid->first());
        }
        $count = ImRoleGroups::find($param['group_id']);
        if (!$count) {
            return errBack('分组不存在');
        }
        $data = ImAccountRoles::with(['roleAuth'])
            ->where('group_id', $param['group_id'])->select(['id', 'name', 'coding', 'created_at'])->get();
        $data = $data->map(function ($val) {
            $authCodes = [];
            foreach ($val->roleAuth as $v) {
                $authCodes[] = $v->auth_id;
            }
            unset($val->roleAuth);
            $val->authCodes = $authCodes;
            return $val;
        });
        return okBack($data);
    }

    /**
     * 编辑角色
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function roleEdit(Request $request)
    {
        $param = $request->all();
        $valid = AuthValidator::handle($param, 'roleEdit');
        if (true !== $valid) {
            return errBack($valid->first());
        }
        $role = ImAccountRoles::find($param['id']);
        if (!$role) {
            return errBack('角色不存在');
        }
        $count = ImAccountRoles::where('id', '<>', $param['id'])->where('name', $param['name'])->count();
        if ($count) {
            return errBack('名称重复');
        }
        $role->name = $param['name'];
        $role->save();
        return okBack();
    }

    /**
     * 删除角色
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function roleDel(Request $request)
    {
        $param = $request->all();
        $valid = AuthValidator::handle($param, 'roleDel');
        if (true !== $valid) {
            return errBack($valid->first());
        }
        $role = ImAccountRoles::select('id')->find($param['id']);
        if (!$role) {
            return errBack('角色不存在');
        }
        $count = ImAccount::where('role_id', $param['id'])->count();
        if ($count) {
            return errBack('请先删除所关联的账号');
        }
        $role->delete();
        return okBack();
    }

    /**
     * 添加菜单
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function menuAdd(Request $request)
    {
        $param = $request->all();
        $valid = AuthValidator::handle($param, 'menuAdd');
        if (true !== $valid) {
            return errBack($valid->first());
        }
        if ($param['parent_id'] > 0 && empty($param['url'])) {
            return errBack('请填写菜单链接');
        }
        try {
            $menu = new ImAuthItems();
            $menu->type = 1;
            $menu->status = $param['status'];
            $menu->name = $param['name'];
            $menu->sort = $param['sort'];
            $menu->logo = $param['logo'] ?? '';
            $menu->url = $param['url'] ?? '';
            $menu->parent_id = $param['parent_id'] ?? 0;
            $menu->auth_code = $param['auth_code'];
            $menu->save();
            return okBack();
        } catch (\Exception $e) {
            return errBack('已存在该权限标识');
        }
    }

    /**
     * 编辑菜单
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function menuEdit(Request $request)
    {
        $param = $request->all();
        $valid = AuthValidator::handle($param, 'menuEdit');
        if (true !== $valid) {
            return errBack($valid->first());
        }
        if ($param['parent_id'] > 0 && empty($param['url'])) {
            return errBack('请填写菜单链接');
        }
        try {
            $menu = ImAuthItems::select('id')->find($param['id']);
            if (!$menu) {
                return errBack('菜单项不存在');
            }
            $menu->type = 1;
            $menu->status = $param['status'];
            $menu->name = $param['name'];
            $menu->sort = $param['sort'];
            $menu->logo = $param['logo'] ?? '';
            $menu->url = $param['url'] ?? '';
            $menu->parent_id = $param['parent_id'] ?? 0;
            $menu->auth_code = $param['auth_code'];
            $menu->save();
            return okBack();
        } catch (\Exception $e) {
            return errBack('已存在该权限标识');
        }
    }

    /**
     * 添加账号
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function accountAdd(Request $request)
    {
        $param = $request->all();
        $valid = AuthValidator::handle($param, 'accountAdd');
        if (true !== $valid) {
            return errBack($valid->first());
        }
        $count = ImAccount::where('phone', $param['phone'])->count();
        if ($count) {
            return errBack('手机号已被注册');
        }
        $role = ImAccountRoles::select('id')->find($param['role_id']);
        if (!$role) {
            return errBack('角色不存在');
        }
        $chatAccount = new ImAccount();
        $chatAccount->username = $param['username'];
        $chatAccount->phone = $param['phone'];
        $chatAccount->sex = $param['sex'];
        $chatAccount->password = Hash::make($param['password']);
        $chatAccount->status = 1;
        $chatAccount->birthday = $param['birthday'] ?? 0;
        $chatAccount->role_id = $param['role_id'];
        $chatAccount->save();
        return okBack();
    }

    /**
     * 账号列表
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function accountList(Request $request)
    {
        $searchWord = $request->get('searchWord');
        list($offset, $limit, $page, $pagesize) = ImAccount::pageProcess();
        $query = ImAccount::with(['accountRole'])
            ->select(['id', 'username', 'phone', 'sex', 'role_id', 'status', 'created_at', 'updated_at'])
            ->where('role_id', '<>', ImAccount::ADMIN_ROLE_ID);
        if (!empty($searchWord)) {
            $query->where(function ($sql) use ($searchWord) {
                $sql->where('username', 'like', '%' . $searchWord . '%')->orWhere('phone', 'like', '%' . $searchWord . '%');
            });
        }
        $total = $query->count();
        $data = $query->offset($offset)->limit($limit)->orderBy('id', 'desc')->get();
        return okBack($data, [
            'total' => $total,
            'page' => $page,
            'pagesize' => $pagesize,
        ]);
    }

    /**
     * 管理员列表
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * @author an
     * @time 2021-12-06 16:46
     */
    public function adminList(Request $request)
    {
        $searchWord = $request->get('searchWord');
        $query = ImAccount::where('role_id', ImAccount::ADMIN_ROLE_ID);
        if (!empty($searchWord)) {
            $query->where(function ($sql) use ($searchWord) {
                $sql->where('username', 'like', $searchWord . '%')
                    ->orWhere('phone', 'like', $searchWord . '%');
            });
        }
        list($offset, $limit, $page, $pagesize) = ImAccount::pageProcess();
        $total = $query->count();
        $data = $query->offset($offset)->limit($limit)
            ->orderBy('id', 'desc')
            ->get(['id', 'username', 'phone', 'sex', 'role_id', 'status', 'created_at', 'updated_at']);
        return okBack($data, [
            'total' => $total,
            'page' => $page,
            'pagesize' => $pagesize,
        ]);
    }

    /**
     * 添加管理员
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * @author an
     * @time 2021-12-06 16:54
     */
    public function adminAdd(Request $request)
    {
        $param = $request->all();
        $valid = AuthValidator::handle($param, 'adminAdd');
        if (true !== $valid) {
            return errBack($valid->first());
        }
        $count = ImAccount::where('phone', $param['phone'])->count();
        if ($count) {
            return errBack('手机号已被注册');
        }
        $role = ImAccountRoles::select('id')->find(1);
        if (!$role) {
            return errBack('超级管理员角色不存在');
        }
        $chatAccount = new ImAccount();
        $chatAccount->username = $param['username'];
        $chatAccount->phone = $param['phone'];
        $chatAccount->sex = $param['sex'];
        $chatAccount->password = Hash::make($param['password']);
        $chatAccount->status = 1;
        $chatAccount->birthday = $param['birthday'] ?? 0;
        $chatAccount->role_id = 1;
        $chatAccount->save();
        return okBack();
    }

    /**
     * 批量删除管理员
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * @author an
     * @time 2021-12-06 17:01
     */
    public function adminDel(Request $request)
    {
        $ids = $request->post('ids');
        $ids = json_decode($ids, true);
        if (empty($ids)) {
            return errBack();
        }
        ImAccount::whereIn('id', $ids)
            ->where('role_id', 1)->delete();
        return okBack();
    }

    /**
     * 编辑账号
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function accountEdit(Request $request)
    {
        $param = $request->all();
        if (isset($param['password'])) {
            $param['edit_password'] = $param['password'];
        }
        $valid = AuthValidator::handle($param, 'accountEdit');
        if (true !== $valid) {
            return errBack($valid->first());
        }
        $imAccount = ImAccount::select('id')->find($param['id']);
        if (!$imAccount) {
            return errBack('账号不存在');
        }
        $imAccount->username = $param['username'];
        $imAccount->phone = $param['phone'];
        $imAccount->sex = $param['sex'];
        $imAccount->role_id = $param['role_id'];
        if (!empty($param['password'])) {
            $imAccount->password = Hash::make($param['password']);
        }
        $imAccount->save();
        return okBack();
    }

    /**
     * 删除账号
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function accountDel(Request $request)
    {
        $ids = $request->post('ids');
        $ids = json_decode($ids, true);
        if (empty($ids)) {
            return errBack('参数错误');
        }
        ImAccount::destroy($ids);
        //添加操作日志
        OperationLogsBusiness::addLog(ImOperationLogs::DELETE, '删除账号;ID:' .
            join(',', $ids));
        return okBack();
    }


    /**
     * 设置角色权限
     * @param Request $request
     * @param role_id 角色ID
     * @param type 1菜单 2菜单操作
     * @param auth_info 权限信息 [{"auth_id":1}]
     * @return \Illuminate\Http\JsonResponse
     */
    public function setRoleAuth(Request $request)
    {
        $param = $request->all();
        $authInfo = json_decode($param['auth_info'], true);
        if (!isset($param['role_id']) || $param['role_id'] <= 0) {
            return errBack('角色信息有误');
        }
        if (empty($authInfo)) {
            return errBack('权限信息有误');
        }
        foreach ($authInfo as $key => &$value) {
            $value['type'] = $param['type'];
            $value['role_id'] = $param['role_id'];
            $valid = AuthValidator::handle($value, 'setRoleAuth');
            if (true !== $valid) {
                return errBack($valid->first());
            }
        }
        $chatRole = ImAccountRoles::select('id')->find($param['role_id']);
        if (!$chatRole) {
            return errBack('角色不存在');
        }
        DB::beginTransaction();
        try {
            ImRoleAuth::where('role_id', $param['role_id'])->where('type', $param['type'])->delete();
            ImRoleAuth::insert($authInfo);
            DB::commit();
            return okBack();
        } catch (\Exception $e) {
            DB::rollBack();
            return errBack('设置失败');
        }
    }

    /**
     * 所有菜单列表
     * @return \Illuminate\Http\JsonResponse
     */
    public function menuList(Request $request)
    {
        $menus = (new AuthBusiness())->loginMenu($request->userInfo['role_id']);
        return okBack($menus);
    }

    /**
     * 添加操作权限
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function setOpAuth(Request $request)
    {
        $param = $request->all();
        $valid = AuthValidator::handle($param, 'setOpAuth');
        if (true !== $valid) {
            return errBack($valid->first());
        }
        try {
            $menu = new ImAuthItems();
            $menu->type = 2;
            $menu->status = 1;
            $menu->name = $param['name'];
            $menu->parent_id = $param['parent_id'];
            $menu->auth_code = $param['auth_code'];
            $menu->save();
            return okBack();
        } catch (\Exception $e) {
            return errBack('已存在该权限标识');
        }
    }

    /**
     * 当前用户操作权限
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function operationAuth(Request $request)
    {
        $operationAuth = $this->authBusiness->operationAuth($request->userInfo['role_id']);
        return okBack($operationAuth);
    }

    /**
     * 登录
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function login(Request $request)
    {
        $param = $request->all();
        $valid = AuthValidator::handle($param, 'login');
        if (true !== $valid) {
            return errBack($valid->first());
        }

        //验证码校验
        $captchaKey = 'webLoginCaptcha:' . $request->ip();

        $session = new ImSessionInfo();
        $captcha = $session->getCaptChaSession($captchaKey);

        if (strtolower($captcha) !== strtolower($request->post('captcha'))) {
            return errBack('图形验证码错误');
        }

        $account = ImAccount::where('phone', $param['username'])->where('status', 1)->first();
        if (!$account) {
            return errBack('账号或密码错误');
        }

        if (!Hash::check($param['password'], $account->password)) {
            return errBack('账号或密码错误');
        }

        DB::beginTransaction();
        try {
            $token = Hash::make($account);
            $token_timeout = config('auth.web_token_timeout');

            if ($request->boolean('remember')) {
                //记住登录，得加时
                $token_timeout = config('auth.web_remember');
            }

            if (!Cache::add($token, $account, $token_timeout)) {
                throw new \Exception('保存失败');
            }

            //删除上一个token
            Cache::forget($account->token);

            //取出账号信息
            $userInfo = $account->makeHidden(['status', 'password', 'deleted_at']);

            //保存用户token
            $account->token = $token;
            $account->online = 1;
            $account->ip = $request->getClientIp();
            $account->save();

            //获取菜单
            $authCodes = (new AuthBusiness())->allAuthCodes($account->role_id);

            DB::commit();
            return okBack(['userInfo' => $userInfo, 'token' => $token, 'expires_in' => $token_timeout, 'authCodes' => $authCodes], ['msg' => '登录成功']);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::info($param['username'] . '登录失败：' . $e->getMessage());
            return errBack('登录失败');
        }
    }

    /**
     * 退出登录
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function logout(Request $request)
    {
        $userInfo = $request->userInfo;
        $account = ImAccount::find($userInfo['id']);
        $account->online = 0;
        $account->save();
        Cache::forget($userInfo['token']);
        return okBack();
    }

    /**
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * @author an
     * @time 2021-12-22 18:31
     */
    public function allRoles(Request $request)
    {
        $data = ImRoleGroups::with(['roles'])->select(['id', 'name'])->get();
        return okBack($data);
    }
}
